<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace buwang\base;

use app\common\model\MemberMiniapp;
use app\common\model\User;
use buwang\exception\MiniappException;
use filter\Inspect;
use buwang\util\Sign;
use buwang\facade\WechatProgram;
use app\Request;
use buwang\service\MiniappService;

class Api extends BaseController
{
    protected $bwapp;      //当前租户访问的应用
    protected $app_id;   //租户应用id

    // 初始化
    protected function initialize()
    {
        parent::initialize();
        $this->bwapp = $this->memberMiniappAuth();//获取当前访问的租户应用信息
        if (!$this->bwapp) throw new MiniappException('应用信息获取验证失败！',403);
        MiniappService::checkMiniappExpire($this->bwapp); //校验应用是否过期
        app('userService')->setInviteCode();   //服务端缓存邀请码
        $this->app_id = $this->bwapp['id'];
        $this->user = $this->user ?: $this->getLoginUser();
    }

    /**
     * 租户应用程序信息
     */
    protected function memberMiniappAuth()
    {
        $appid = $this->request->param('service_id', '');
        $condition = [];
        $header = $this->request->header();
        if (empty($appid)) {
            if (empty($header['request-app'])) throw new MiniappException('header check fail',403);
            $condition['service_id'] = Inspect::filter_escape($header['request-app']);
        } else {
            $condition['service_id'] = Inspect::filter_escape($appid);
        }
        $condition['is_lock'] = 0;
        $this->token = $this->token ?: get_token($this->request);
        return MemberMiniapp::where($condition)->field('id,member_id,appname,service_id,navbar_color,navbar_style,create_time,update_time,expire_time,miniapp_appid,miniapp_id,mp_appid')->cache(false)->find();
    }

    /**
     * 禁止用户登录
     * @param int $code
     * @return \think\Response
     */
    protected function isUserAuth(int $code = 401)
    {
        if (!$this->user) {
            return $this->code($code)->error('API验证获取用户信息失败');
        }
    }

    /**
     * 获取token对应的用户信息
     */
    protected function getLoginUser()
    {
        $token = get_token($this->request);
        if ($token) {
            try{
                $user = self::decodeToken($token)->data;//解析token,获取用户信息
                if ($user && $user->id) {
                    return User::where(['id' => $user->id, 'status' => 0])->find();
                }
            }catch (\Throwable $e){
                return [];
            }
        }
        return [];
    }

    /**
     * API获取用户数据
     * @return \think\Response
     */
    public function getUserInfo(): \think\Response
    {
        self::isUserAuth();
        $data['id'] = $this->user->id;
        $data['invite_code'] = $this->user->invite_code;
        $data['mobile'] = empty($this->user->mobile) ? '' : en_mobile($this->user->mobile);
        $data['invite_code'] = $this->user->invite_code;
        $data['avatar'] = $this->user->avatar;
        $data['nickname'] = $this->user->nickname;
        $data['login_time'] = date('Y-m-d', $this->user->login_time);
        return $this->success('获取成功', $data);
    }

    /**
     * 接口验证参数
     * @param mixed $var 签名验证的参数
     * @param string $signType 默认为md5
     * @return array
     */
    protected function apiSignCheck($var = [], string $signType = 'md5'): array
    {
        if (empty($var['sign'])) {
            $code = 401;
            $msg = '没有验证签名';
        } else {
            $secret = $this->bwapp->service_id;
            if (empty($var['publickey']) && empty($secret)) {
                $code = 403;
                $msg = '签名秘钥或公钥错误';
            } else {
                $sign = Sign::createSignature($var, $secret, $signType);//参数验签
                if ($var['sign'] == $sign) {
                    $code = 200;
                    $msg = '验签成功';
                } else {
                    $code = 403;
                    $msg = '参数验证失败';
                }
            }
        }
        return ['msg' => $msg, 'code' => $code];
    }

    /**
     * 生成小程序码 获取unlimited小程序码
     * @param array $scene 场景
     * @param string $page 路径
     * @param string $name 文件名
     * @return \think\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
     */
    public function getProgramCode(array $scene, string $page, string $name): \think\Response
    {
        if (request()->isPost()) {
            if(mb_strlen(http_build_query($scene) > 32)) return $this->error('场景值只支持最大32个可见字符');
            $filepath = public_path('qrcode');
            $response = WechatProgram::getWechatObj($this->app_id)->app_code->getUnlimit(http_build_query($scene), ['page' => Inspect::filter_escape($page)]);
            if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $filename = $response->saveAs($filepath, md5($name));
                $path = '/' . str_replace('\\', '/', substr($filepath . $filename, strlen(public_path())));
                return $this->success('成功', ['url' => Request::root(true) . $path]);
            }
            return $this->error('您的应用未上线,无法生成小程序码');
        }
        return $this->error('请求类型错误');
    }

    /**
     * 生成小程序码二维码 (不推荐使用)
     * @param array $scene
     * @param string $page 路径
     * @param string $name 文件名
     * @return \think\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
     */
    public function getProgramQrCode(array $scene, string $page,string $name)
    {
        if (request()->isPost()) {
            $filepath = public_path('qrcode');
            $response = WechatProgram::getWechatObj($this->app_id)->app_code->getQrCode($page . '?' . http_build_query($scene));
            if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $filename = $response->saveAs($filepath, md5($name));
                $path = '/' . str_replace('\\', '/', substr($filepath . $filename, strlen(public_path())));
                return $this->success('成功', ['url' => Request::root(true) . $path]);
            }
            return $this->error('您的应用未上线，无法生成小程序码二维码');
        }
        return $this->error('请求类型错误');
    }


}